package com.jasonchoi.security.commons.config;

import com.jasonchoi.security.commons.security.LoginFailureHandler;
import com.jasonchoi.security.commons.security.LoginSuccessHandler;
import com.jasonchoi.security.commons.security.MyFilterSecurityInterceptor;
import com.jasonchoi.security.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * 用户认证 通过implement UserDetailsService
 * 动态授权 方式二
 *         自定义implements FilterInvocationSecurityMetadataSource 获取当前资源需要的访问角色
 *         自定义拦截器 进行前置拦截 通过setAccessDecisionManager 注入自定义的的MetadataSource
 *         自定义决策控制器 implement AccessDecisionManager 进行角色与资源匹配投票
 *         公共权限调用 返回空集合或者null 会被拦截(疑问 这里两种方式对公共权限的实现效果有点不同)
 * @Author: JasonChoi
 * @Date: 2020/1/2 16:29
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyFilterSecurityInterceptor myFilterSecurityInterceptor;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new UserService()).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 关闭csrf
        http.csrf().disable();

        // 登录配置
        http.formLogin().loginPage("/auth/login").loginProcessingUrl("/login").permitAll()
            .successHandler(new LoginSuccessHandler()).failureHandler(new LoginFailureHandler())
            .and().logout().permitAll();


        // 授权配置
        http.authorizeRequests()
            /* 无需授权访问 */
            .antMatchers("/", "/auth/login").permitAll()
            .antMatchers("/js/**", "/css/**", "/images/**").permitAll()
            .anyRequest().authenticated()
            .and().addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
    }

}
